// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//


#pragma once

#include <pollux/common/compression/compression.h>
#include <pollux/common/config/config.h>
#include <pollux/dwio/common/data_buffer.h>
#include <pollux/dwio/common/file_sink.h>
#include <pollux/dwio/common/flush_policy.h>
#include <pollux/dwio/common/options.h>
#include <pollux/dwio/common/writer.h>
#include <pollux/dwio/common/writer_factory.h>
#include <pollux/dwio/text/writer/buffered_writer_sink.h>
#include <pollux/vector/complex_vector.h>

namespace kumo::pollux::text {
    struct WriterOptions : public dwio::common::WriterOptions {
        int64_t defaultFlushCount = 10 << 10;
    };

    // TODO: move to a separate file to be shared with text reader once it is in oss
    class TextFileTraits {
    public:
        //// The following constants define the delimiters used by TextFile format.
        /// Each row is separated by 'kNewLine'.
        /// Each column is separated by 'kSOH' within each row.

        /// String for null data.
        static inline const std::string kNullData = "\\N";

        /// Delimiter between columns.
        static const char kSOH = '\x01';

        /// Delimiter between rows.
        static const char kNewLine = '\n';
    };

    /// Encodes Pollux vectors in TextFormat and writes into a FileSink.
    class TextWriter : public dwio::common::Writer {
    public:
        /// Constructs a writer with output to a 'sink'.
        /// @param schema specifies the file's overall schema, and it is always
        /// non-null.
        /// @param sink output sink
        /// @param options writer options
        TextWriter(
            RowTypePtr schema,
            std::unique_ptr<dwio::common::FileSink> sink,
            const std::shared_ptr<text::WriterOptions> &options);

        ~TextWriter() override = default;

        void write(const VectorPtr &data) override;

        void flush() override;

        bool finish() override {
            close();
            return true;
        }

        void close() override;

        void abort() override;

    private:
        void write_cell_value(
            const std::shared_ptr<DecodedVector> &decodedColumnVector,
            const TypePtr &type,
            vector_size_t row);

        const RowTypePtr schema_;
        const std::unique_ptr<BufferedWriterSink> bufferedWriterSink_;
    };

    class TextWriterFactory : public dwio::common::WriterFactory {
    public:
        TextWriterFactory() : WriterFactory(dwio::common::FileFormat::TEXT) {
        }

        std::unique_ptr<dwio::common::Writer> createWriter(
            std::unique_ptr<dwio::common::FileSink> sink,
            const std::shared_ptr<dwio::common::WriterOptions> &options) override;

        std::unique_ptr<dwio::common::WriterOptions> createWriterOptions() override;
    };
} // namespace kumo::pollux::text
